<template>
    <div class="search">
        <div class="searchItems" v-for="item in searchItems" :key="item.label">
            <div class="item">
                <div v-if="page === 'depmap' && item.type === 'conditional-select'" class="label">
                    <div v-if="index[item.label]">{{ item.label }}:</div>
                </div>
                <div v-if="item.type === 'tab-select' || item.type === 'tab-multi-select'"></div>
                <div v-else class="label">{{ item.label }}:</div>
                <div class="select-container">
                    <div v-if="item.type == 'single-select'">
                        <SingleSelect v-model="selectedValues" :searchItem="item" :updateOptions="updateOptions" />
                    </div>
                    <div v-if="item.type == 'multi-select'">
                        <MultiSelect
                            ref="selectMultiRef"
                            v-model="selectedValues"
                            :searchItem="item"
                            :updateOptions="updateOptions"
                            :filteredOptions="filteredOptions"
                        />
                    </div>
                    <div v-if="item.type === 'Chrom'">
                        <Chrom v-model="selectedValues" :searchItem="item" :updateOptions="updateOptions" />
                    </div>
                    <div v-if="item.type === 'switch'">
                        <div v-for="ele in item.choices" :key="ele.label">
                            <div class="switchItem">
                                <div class="switchLabel">
                                    {{ ele.label }}
                                </div>
                                <div class="switchValue">
                                    <el-switch
                                        v-model="selectedValues[item.value][ele.value]"
                                        @change="handleSwitchChange($event, ele.label)"
                                    />
                                </div>
                            </div>
                        </div>
                    </div>
                    <div v-if="item.type === 'conditional-select'">
                        <el-select-v2
                            class="bar"
                            v-model="selectedValues[item.value]"
                            :options="item.options"
                            placeholder="Select"
                            clearable
                            v-if="index[item.label]"
                        ></el-select-v2>
                    </div>

                    <div v-if="item.type === 'tab-multi-select'">
                        <TabMultiSelect
                            ref="selectTabMultiRef"
                            v-model="selectedValues"
                            :searchItem="item"
                            :updateOptions="updateOptions"
                            :activeName="activeName"
                            @updateValues="handleUpdateValues"
                            :filteredOptions="filteredOptions"
                        />
                    </div>
                    <div v-if="item.type === 'numRange'">
                        <NumberRange v-model="selectedValues" :searchItem="item" />
                    </div>
                    <div v-if="item.type === 'grouped-single-select'">
                        <GroupedSingleSelect v-model="selectedValues" :searchItem="item" />
                    </div>
                </div>
            </div>
        </div>
        <div class="buttons">
            <el-button class="buttonItem" type="info" @click="searchFunc">Search</el-button>
        </div>
    </div>
</template>

<script lang="ts" setup props="props" name="Search">
    import { onBeforeMount, reactive, ref, computed, watch } from 'vue';
    import { ElMessage } from 'element-plus';
    import { get, post } from '../axios/api';
    import MultiSelect from '@/components/searchComponents/MultiSelect.vue';
    import SingleSelect from '@/components/searchComponents/SingleSelect.vue';
    import TabMultiSelect from '@/components/searchComponents/TabMultiSelect.vue';
    import NumberRange from '@/components/searchComponents//NumberRange.vue';
    import GroupedSingleSelect from '@/components/searchComponents//GroupedSingleSelect.vue';
    import Chrom from '@/components/searchComponents//Chrom.vue';

    let index: any = ref({});
    let page = ref('');
    let selectedValues: any = ref({});
    const props = defineProps([
        'searchItems',
        'updateTable',
        'downloadData',
        'initSelectedValues',
        'page',
        'showDownload'
    ]);
    let tabItems: any = ref([]);
    let activeName = '';
    let rangeItemList: any = ref([]);
    const selectMultiRef: any = ref();

    function searchFunc() {
        let chrom = selectedValues.value.Chrom1;
        let chromRange = selectedValues.value.ChromRange;
        let message = '';
        let err = false;

        const reg = /^\d+$/;
        if (chromRange && !chrom) {
            err = true;
            message = 'Please Select Chrom';
        } else if (chrom && chromRange) {
            if (chromRange && chromRange.indexOf('-') === -1) {
                err = true;
                message = "Please seperate start and end with '-'";
            }
            let nums = chromRange.split('-');

            if (reg.test(nums[0]) && reg.test(nums[1])) {
                if (parseInt(nums[0]) > parseInt(nums[1])) {
                    err = true;
                    message = 'Start must be less than end';
                }
            } else {
                err = true;
                message = 'Start or End must be a number';
            }
        }
        if (rangeItemList.value.length > 0) {
            // 可以同时为空 不能一个有值一个为空 大小关系不能错
            for (let ele of rangeItemList.value) {
                let eleLabel = selectedValues.value[ele];
                if ((eleLabel.min === null || eleLabel.min === '') && (eleLabel.max === null || eleLabel.max === '')) {
                    continue;
                } else if (
                    eleLabel.min === null ||
                    eleLabel.min === '' ||
                    eleLabel.max === null ||
                    eleLabel.max === ''
                ) {
                    err = true;
                    message = 'Min or Max cannot be empty';
                } else {
                    if (eleLabel.min > eleLabel.max) {
                        err = true;
                        message = 'Min must less than Max';
                    }
                    if (eleLabel.min < 0 || eleLabel.max < 0) {
                        err = true;
                        message = 'Min or Max must equal or greater 0';
                    }
                }
            }
        }

        if (err) {
            ElMessage({
                message: message,
                type: 'error'
            });
        } else {
            props.updateTable(selectedValues.value);
        }
    }

    function handleSwitchChange(event: any, item: any) {
        if (item === 'Gene' || item === 'Expression') {
            index.value['Gene'] =
                selectedValues.value.DataType.depmap_diff_gene_analysis ||
                selectedValues.value.DataType.depmap_diff_expression_analysis;
        } else {
            index.value[item] = event;
        }
    }

    // 每次选择了选项之后就开始更新，清空选项也更新
    async function updateOptions(refs?: any) {
        //  根据selectValues 确定params和options 确定返回结果
        //  将返回结果直接赋值给searchItems
        //  params 是已经确定了的数据，需要根据params进行筛选，如果params为空，则判断options里是否有对应数据
        //  下边代码作用是多选的时候输入query并确定选项后，去掉query文字

        if (refs && refs.selectMultiRef) {
            refs.selectMultiRef.states.inputValue = '';
            refs.selectMultiRef.toggleMenu();
        }

        if (refs && refs.selectMultiTabRef) {
            refs.selectMultiTabRef[0].states.inputValue = '';
            refs.selectMultiTabRef[0].toggleMenu();
        }

        let params: any = selectedValues.value;
        let options = [];
        // 如果没有确定的选项那就是一定要更新options
        for (let opt in selectedValues.value) {
            if (!selectedValues.value[opt]) {
                options.push(opt);
            }
        }
        let res: any = await post('/update_options/', { params, options, dataType: page.value });
        if (res && res.success) {
            for (let d of res.data) {
                for (let ele of props.searchItems) {
                    if (ele.type === 'tab-select' || ele.type === 'tab-multi-select') {
                        let target = ele.tabs.find((el: any) => el.value === d.label);
                        if (target) {
                            target.options = d.data;
                        }
                    } else {
                        if (ele.value && ele.value === d.label) {
                            ele.options = d.data;
                        }
                    }
                }
            }
        } else {
            ElMessage({
                message: res.msg ? res.msg : 'An error occured',
                type: 'error'
            });
        }
    }

    function downloadFunc() {
        props.downloadData(selectedValues.value);
    }

    const filteredOptions = (ele: any) => {
        // 直接返回的是Object类型的数据，用的时候加上.value
        return computed(() => {
            const options = Array.isArray(ele.options) ? ele.options : [];
            return options.filter((option: any) => !selectedValues.value[ele.value]?.includes(option.value));
        });
    };

    onBeforeMount(() => {
        page.value = props.page;
        props.searchItems.forEach(
            ({
                value,
                type,
                choices,
                tabs
            }: {
                options: any;
                value: string;
                type: string;
                choices: any;
                tabs: any;
            }) => {
                if (type === 'switch') {
                    selectedValues.value[value] = {};
                    for (let ele of choices) {
                        selectedValues.value[value][ele.value] = ele.isChosen;
                    }
                } else if (type === 'tab-select' || type === 'tab-multi-select') {
                    selectedValues.value[value] = '';
                    tabItems.value = tabs;
                    for (let ele of tabs) {
                        if (ele.isChosen) {
                            activeName = ele.value;
                        }
                    }
                } else if (type === 'numRange') {
                    selectedValues.value[value] = {};
                    selectedValues.value[value]['min'] = null;
                    selectedValues.value[value]['max'] = null;
                    rangeItemList.value.push(value);
                } else {
                    selectedValues.value[value] = '';
                }
            }
        );
        if (props.page === 'ecDNA') {
            if (props.initSelectedValues && props.initSelectedValues.Tissue) {
                selectedValues.value['Tissue'] = props.initSelectedValues.Tissue;
            }
            if (props.initSelectedValues && props.initSelectedValues.TumorType) {
                selectedValues.value['TumorType'] = props.initSelectedValues.TumorType;
            }
            if (props.initSelectedValues && props.initSelectedValues.Cellline) {
                selectedValues.value['Cellline'] = props.initSelectedValues.Cellline;
            }
        } else if (props.page === 'depmap') {
            if (props.initSelectedValues && 'DrugTarget' in props.initSelectedValues) {
                activeName = 'DrugTarget';
                selectedValues.value['DrugTarget'] = props.initSelectedValues.DrugTarget;
                selectedValues.value['TumorType'] = props.initSelectedValues.TumorType;
            } else {
                if (props.initSelectedValues) {
                    activeName = 'GeneTarget';
                    selectedValues.value['GeneTarget'] = props.initSelectedValues.Target;
                    selectedValues.value['TumorType'] = props.initSelectedValues.TumorType;
                }
            }
        }
    });

    function handleUpdateValues(newValues: any) {
        selectedValues.value = newValues;
        props.updateTable(selectedValues.value);
    }
</script>

<style scoped>
    .search {
        width: 100%;
        display: flex;
        flex-wrap: wrap;
        flex-direction: row;
        align-items: flex-end;
        justify-content: flex-start;
        background-color: white;
        border-radius: 4px;
        padding: 20px 0;
    }

    .searchItems {
        width: 220px;
        display: flex;
        flex-direction: column;
        justify-content: space-around;
        /* margin: 10px; */
    }

    .buttons {
        width: 80px;
        /* justify-content: space-between; */
    }
    .item {
        /* display: flex; */
        width: 100%;
    }

    .bar {
        margin-left: 20px;
        width: 80%;
    }

    .label {
        /* width: 100%; */
        margin: 10px 10px 10px 30px;
        font-family: 'Helvetica Neue';
        font-weight: 500;
    }
    .select-container {
        width: 100%;
        margin-left: 10px;
    }
    /* .el-button+.el-button { 
        margin-left: 0; 
    } */
    .switchItem {
        width: 100%;
        display: flex;
        flex-wrap: nowrap;
        justify-content: space-between;
        align-items: center;
    }
    .switchLabel {
        width: 100%;
        margin-right: 10px;
    }

    .demo-tabs {
        width: 100%;
        border-radius: 4px;
    }
    :deep(.el-tabs__header) {
        border-radius: 4px !important;
        font-family: 'Helvetica Neue';
    }
    :deep(.is-active) {
        background-color: white;
    }

    .switchValue {
        width: 100%;
    }

    .buttonItem {
        width: 100%;
        margin-left: 40px;
        margin-top: 20px;
        background-color: #337ab7;
        border-color: #2e6da4;
        font-weight: 400;
    }
</style>
